<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  
  
  <title>跨域解决方案 | 漠北烟云</title>
  <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
  <meta name="description" content="只有弱者才会恐惧阴影，于是恐惧便压倒了他们。什么是跨域?同源策略:这里的源(origin)指的是协议、域名、端口号，同源指的是在url中协议、域名、端口号均相同。那么同源策略是浏览器的一个安全功能，不同源的脚本在没有明确授权的情况下，不能读写对方资源。 注意这个“不能读写资源”的含义，它主要限制了以下三个方面： Cookie、LocalStorage 和 IndexDB 无法读取DOM 和 JS">
<meta property="og:type" content="article">
<meta property="og:title" content="跨域解决方案">
<meta property="og:url" content="http://example.com/2023/03/02/%E8%B7%A8%E5%9F%9F%E8%A7%A3%E5%86%B3%E6%96%B9%E6%A1%88/index.html">
<meta property="og:site_name" content="漠北烟云">
<meta property="og:description" content="只有弱者才会恐惧阴影，于是恐惧便压倒了他们。什么是跨域?同源策略:这里的源(origin)指的是协议、域名、端口号，同源指的是在url中协议、域名、端口号均相同。那么同源策略是浏览器的一个安全功能，不同源的脚本在没有明确授权的情况下，不能读写对方资源。 注意这个“不能读写资源”的含义，它主要限制了以下三个方面： Cookie、LocalStorage 和 IndexDB 无法读取DOM 和 JS">
<meta property="og:locale" content="en_US">
<meta property="article:published_time" content="2023-03-01T16:03:45.000Z">
<meta property="article:modified_time" content="2023-03-26T14:54:31.835Z">
<meta property="article:author" content="mobeiyanyun">
<meta property="article:tag" content="js基础">
<meta name="twitter:card" content="summary">
  
    <link rel="alternate" href="/atom.xml" title="漠北烟云" type="application/atom+xml">
  
  
    <link rel="shortcut icon" href="/favicon.png">
  
  
    
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/typeface-source-code-pro@0.0.71/index.min.css">

  
  
<link rel="stylesheet" href="/css/style.css">

  
    
<link rel="stylesheet" href="/fancybox/jquery.fancybox.min.css">

  
<meta name="generator" content="Hexo 6.3.0"></head>

<body>
  <div id="container">
    <div id="wrap">
      <header id="header">
  <div id="banner"></div>
  <div id="header-outer" class="outer">
    <div id="header-title" class="inner">
      <h1 id="logo-wrap">
        <a href="/" id="logo">漠北烟云</a>
      </h1>
      
    </div>
    <div id="header-inner" class="inner">
      <nav id="main-nav">
        <a id="main-nav-toggle" class="nav-icon"></a>
        
          <a class="main-nav-link" href="/">Home</a>
        
          <a class="main-nav-link" href="/archives">Archives</a>
        
      </nav>
      <nav id="sub-nav">
        
          <a id="nav-rss-link" class="nav-icon" href="/atom.xml" title="RSS Feed"></a>
        
        <a id="nav-search-btn" class="nav-icon" title="Search"></a>
      </nav>
      <div id="search-form-wrap">
        <form action="//google.com/search" method="get" accept-charset="UTF-8" class="search-form"><input type="search" name="q" class="search-form-input" placeholder="Search"><button type="submit" class="search-form-submit">&#xF002;</button><input type="hidden" name="sitesearch" value="http://example.com"></form>
      </div>
    </div>
  </div>
</header>

      <div class="outer">
        <section id="main"><article id="post-跨域解决方案" class="h-entry article article-type-post" itemprop="blogPost" itemscope itemtype="https://schema.org/BlogPosting">
  <div class="article-meta">
    <a href="/2023/03/02/%E8%B7%A8%E5%9F%9F%E8%A7%A3%E5%86%B3%E6%96%B9%E6%A1%88/" class="article-date">
  <time class="dt-published" datetime="2023-03-01T16:03:45.000Z" itemprop="datePublished">2023-03-02</time>
</a>
    
  </div>
  <div class="article-inner">
    
    
      <header class="article-header">
        
  
    <h1 class="p-name article-title" itemprop="headline name">
      跨域解决方案
    </h1>
  

      </header>
    
    <div class="e-content article-entry" itemprop="articleBody">
      
        <h2 id="只有弱者才会恐惧阴影，于是恐惧便压倒了他们。"><a href="#只有弱者才会恐惧阴影，于是恐惧便压倒了他们。" class="headerlink" title="只有弱者才会恐惧阴影，于是恐惧便压倒了他们。"></a>只有弱者才会恐惧阴影，于是恐惧便压倒了他们。</h2><h5 id="什么是跨域"><a href="#什么是跨域" class="headerlink" title="什么是跨域?"></a>什么是跨域?</h5><p>同源策略:这里的源(origin)指的是协议、域名、端口号，同源指的是在url中协议、域名、端口号均相同。那么同源策略是浏览器的一个安全功能，不同源的脚本在没有明确授权的情况下，不能读写对方资源。</p>
<p>注意这个“不能读写资源”的含义，它主要限制了以下三个方面：</p>
<p>Cookie、LocalStorage 和 IndexDB 无法读取<br>DOM 和 JS 对象无法获取<br>Ajax请求发送不出去<br>只要协议、域名、端口有任何一个不同，都被当作是不同的域，这就是所谓“跨域”。</p>
<p>虽然同源策略带来了安全上的保证，但是实际业务中，跨域的场景实在是太多了。如果仅仅因为跨域就导致资源无法互相读写，那么我们现在看到的许多互联网功能都将原地歇菜。之所以没歇菜，是因为网络策略有其灵活性，我们可以通过一些方式来绕过同源策略、达到通信目的。</p>
<h5 id="跨域解决方案"><a href="#跨域解决方案" class="headerlink" title="跨域解决方案"></a>跨域解决方案</h5><h6 id="1-JSONP"><a href="#1-JSONP" class="headerlink" title="1) JSONP:"></a>1) JSONP:</h6><p>由于js调用跨域文件是被允许的。只要我们在远程服务器上设法把数据装进js格式的文件里，就可以供客户端调用和进一步处理。</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line">&lt;!DOCTYPE html&gt;</span><br><span class="line">&lt;html&gt;</span><br><span class="line">    &lt;body&gt;</span><br><span class="line">        &lt;script <span class="built_in">type</span>=<span class="string">&quot;text/javascript&quot;</span>&gt;</span><br><span class="line">            // callback是存在服务端的</span><br><span class="line">            <span class="keyword">function</span> callback(data) &#123;</span><br><span class="line">                console.log(data)</span><br><span class="line">            &#125;</span><br><span class="line">        &lt;/script&gt;</span><br><span class="line">        // 这里引入服务端代码</span><br><span class="line">        &lt;script src=<span class="string">&quot;http://www.xxxx.com/jsonp&quot;</span> <span class="built_in">type</span>=<span class="string">&quot;text/javascript&quot;</span> charset=<span class="string">&quot;utf-8&quot;</span>&gt;&lt;/script&gt;</span><br><span class="line">    &lt;/body&gt;</span><br><span class="line">&lt;/html&gt;</span><br></pre></td></tr></table></figure>
<h6 id="2-CORS"><a href="#2-CORS" class="headerlink" title="2) CORS:"></a>2) CORS:</h6><p>CORS是一个W3C标准，全称是”跨域资源共享”（Cross-origin resource sharing）。</p>
<p>它允许浏览器向不同源的服务器，发出XMLHttpRequest请求。虽然需要浏览器和服务器同时支持，但目前来看，除了低版本 IE 外，基本所有浏览器都支持该功能。</p>
<p>CORS的通信过程，实际上不需要什么代码层面的配合与改动，由浏览器自动实现。</p>
<p>对于开发者来说，CORS通信与同源的通信没有差别，至少代码上是一样的。浏览器一旦发现AJAX请求跨域，就会自动添加一些附加的头信息、追加必要的请求，但用户不会有感觉。</p>
<p>浏览器的行为是通用的、自动化的。因此能否实现 CORS 的关键，其实在于服务器是否对此提供支持。我们下面从过程来理解一下浏览器和服务器在 CORS 上的合作机制：</p>
<p>简单请求对应的 CORS 行为</p>
<p>浏览器会把请求分为简单请求和非简单请求，对于这两种请求，CORS 的处理过程是不同的，我们先来看简单请求：</p>
<p>请求方式为HEAD、POST 或者 GET<br>http头信息不超出以下字段：Accept、Accept-Language 、 Content-Language、 Last-Event-ID、 Content-Type(限于三个值：application&#x2F;x-www-form-urlencoded、multipart&#x2F;form-data、text&#x2F;plain)</p>
<p>满足这两个条件的，就是简单请求。对于简单请求，对于简单请求，浏览器直接发出CORS请求。具体来说，就是在头信息之中，增加一个Origin字段：</p>
<p>Origin: <a target="_blank" rel="noopener" href="http://baidu.com/">http://baidu.com</a><br>Origin字段用来说明，本次请求来自哪个源（协议 + 域名 + 端口）。服务器根据这个值，决定是否同意这次请求。服务器处理的结果，分为两种情况：</p>
<p>不同意： 如果Origin指定的源，不在许可范围内，服务器会返回一个正常的HTTP回应；浏览器发现，这个回应的头信息没有包含Access-Control-Allow-Origin字段，就知道出错了，从而抛出一个错误，被 XMLHttpRequest 的 onerror 回调函数捕获。<br>同意：如果Origin指定的域名在许可范围内，服务器返回的响应，会多出这个关键的头信息字段：<br>Access-Control-Allow-Origin: <a target="_blank" rel="noopener" href="http://baidu.com/">http://baidu.com</a><br>这个字段用于说明服务器接纳哪些域名。它的值要么是请求时Origin字段的值，要么是一个*——表示接受任意域名的请求。</p>
<p>复杂请求对应的 CORS 行为<br>有一些请求对服务器有着特殊的要求，比如请求方法是PUT或DELETE，或者Content-Type字段的类型是application&#x2F;json。</p>
<p>非简单请求的CORS请求，会在正式通信之前，增加一次HTTP查询请求，称为”预检”请求（preflight）。</p>
<p>这个 preflight 的作用在于，确认当前网页所在的域名是否在服务器的许可名单之中、明确可以使用的 HTTP 请求方法和头信息字段。只有在这个请求返回成功的情况下，浏览器才会发出正式的请求。</p>
<p>这样做的目的是为了避免“无用功”。要知道，一般来说，正式请求要携带一些信息，它体积可能比较大。如果我们背着这么大一个包袱到了服务端那边，却发现对方根本不接受你，那岂不是白费力气了嘛。所以说，发送正式请求前先“预检”，就跟结婚之前要先订婚一样，是一个必要的确认动作。</p>
<p>CORS 和 JSONP 的对比<br>CORS 的优势，往往是相对于 JSONP 来说的：JSONP只支持GET请求，而CORS支持所有类型的HTTP请求。但相应地，JSONP在低版本 IE 上也可以畅通无阻，CORS 就没有这么好的兼容性了。</p>
<h6 id="3-postMessage跨域"><a href="#3-postMessage跨域" class="headerlink" title="3) postMessage跨域"></a>3) postMessage跨域</h6><p>这个 API 从 H5 开始支持，通过注册监听信息的Message事件、调用发送信息的postMessage方法，我们可以实现跨窗口通信。</p>
<p>从广义上讲，一个窗口可以获得对另一个窗口的引用（比如 targetWindow &#x3D; window.opener），然后在窗口上调用 targetWindow.postMessage() 方法分发一个 MessageEvent 消息。接收消息的窗口可以根据需要自由处理此事件。传递给 window.postMessage() 的参数（比如 message ）将通过消息事件对象暴露给接收消息的窗口。</p>
<p>发送信息的postMessage方法<br>otherWindow.postMessage(message, targetOrigin, [transfer]);<br>这里otherWindow是对目标窗口的引用；message是要发送的消息；targetOrigin是限定消息接受范围，一般是字符串或者URI，星号 * 则意味着不限制。</p>
<p>接受信息的message事件</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">var onmessage = <span class="keyword">function</span>(event) &#123;</span><br><span class="line">  var data = event.data;</span><br><span class="line">  var origin = event.origin;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">if</span>(typeof window.addEventListener != <span class="string">&#x27;undefined&#x27;</span>)&#123;</span><br><span class="line">    window.addEventListener(<span class="string">&#x27;message&#x27;</span>,onmessage,<span class="literal">false</span>);</span><br><span class="line">&#125;<span class="keyword">else</span> <span class="keyword">if</span>(typeof window.attachEvent != <span class="string">&#x27;undefined&#x27;</span>)&#123;</span><br><span class="line">    window.attachEvent(<span class="string">&#x27;onmessage&#x27;</span>, onmessage);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>流程演示<br>下面我们通过一个例子来理解这个过程：<br>a页面中对消息接受和派发的处理：<br>a页面</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line">&lt;iframe <span class="built_in">id</span>=<span class="string">&quot;iframe&quot;</span> src=<span class="string">&quot;http://www.xxxx/b.html&quot;</span> style=<span class="string">&quot;display:none;&quot;</span>&gt;&lt;/iframe&gt;</span><br><span class="line">&lt;script&gt;       </span><br><span class="line">    var iframe = document.getElementById(<span class="string">&#x27;iframe&#x27;</span>);</span><br><span class="line">    iframe.onload = <span class="function"><span class="title">function</span></span>() &#123;</span><br><span class="line">        var data = &#123;</span><br><span class="line">            name: <span class="string">&#x27;xiuyan&#x27;</span></span><br><span class="line">        &#125;;</span><br><span class="line">        // a 页面向 b 页面派发消息</span><br><span class="line">        iframe.contentWindow.postMessage(JSON.stringify(data), <span class="string">&#x27;http://www.neal.cn&#x27;</span>);</span><br><span class="line">    &#125;;</span><br><span class="line"></span><br><span class="line">    // a 页面接受 b 页面的消息</span><br><span class="line">   window.addEventListener(<span class="string">&quot;message&quot;</span>, <span class="keyword">function</span>( event ) &#123;</span><br><span class="line">      console.log(<span class="string">&#x27;data from b is&#x27;</span>, event.data)</span><br><span class="line">   &#125;);</span><br><span class="line">&lt;/script&gt;</span><br></pre></td></tr></table></figure>
<p>b页面对消息接受和派发的处理：</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line">&lt;script&gt;</span><br><span class="line">    // 接收 a 页面的数据</span><br><span class="line">    window.addEventListener(<span class="string">&#x27;message&#x27;</span>, <span class="keyword">function</span>(e) &#123;</span><br><span class="line">      console.log(<span class="string">&#x27;data from a is&#x27;</span>, event.data)</span><br><span class="line"></span><br><span class="line">        var data = JSON.parse(e.data);</span><br><span class="line">        <span class="keyword">if</span> (data) &#123;</span><br><span class="line">            data.age = 100;</span><br><span class="line"></span><br><span class="line">            // 派发数据到 a 页面</span><br><span class="line">            window.parent.postMessage(JSON.stringify(data), <span class="string">&#x27;http://www.xxxx.com&#x27;</span>);</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;, <span class="literal">false</span>);</span><br><span class="line">&lt;/script&gt;</span><br></pre></td></tr></table></figure>
      
    </div>
    <footer class="article-footer">
      <a data-url="http://example.com/2023/03/02/%E8%B7%A8%E5%9F%9F%E8%A7%A3%E5%86%B3%E6%96%B9%E6%A1%88/" data-id="clfziy0ow000tp5r443ljbpig" data-title="跨域解决方案" class="article-share-link">Share</a>
      
      
      
  <ul class="article-tag-list" itemprop="keywords"><li class="article-tag-list-item"><a class="article-tag-list-link" href="/tags/js%E5%9F%BA%E7%A1%80/" rel="tag">js基础</a></li></ul>

    </footer>
  </div>
  
    
<nav id="article-nav">
  
    <a href="/2023/03/02/vue-nextTick/" id="article-nav-newer" class="article-nav-link-wrap">
      <strong class="article-nav-caption">Newer</strong>
      <div class="article-nav-title">
        
          vue-nextTick
        
      </div>
    </a>
  
  
</nav>

  
</article>


</section>
        
          <aside id="sidebar">
  
    

  
    
  <div class="widget-wrap">
    <h3 class="widget-title">Tags</h3>
    <div class="widget">
      <ul class="tag-list" itemprop="keywords"><li class="tag-list-item"><a class="tag-list-link" href="/tags/VUE/" rel="tag">VUE</a></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/js%E5%9F%BA%E7%A1%80/" rel="tag">js基础</a></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/%E5%B0%8F%E7%A8%8B%E5%BA%8F-uniapp/" rel="tag">小程序&#x2F;uniapp</a></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/%E6%B7%B7%E5%90%88%E5%BC%80%E5%8F%91/" rel="tag">混合开发</a></li></ul>
    </div>
  </div>


  
    
  <div class="widget-wrap">
    <h3 class="widget-title">Tag Cloud</h3>
    <div class="widget tagcloud">
      <a href="/tags/VUE/" style="font-size: 15px;">VUE</a> <a href="/tags/js%E5%9F%BA%E7%A1%80/" style="font-size: 20px;">js基础</a> <a href="/tags/%E5%B0%8F%E7%A8%8B%E5%BA%8F-uniapp/" style="font-size: 10px;">小程序/uniapp</a> <a href="/tags/%E6%B7%B7%E5%90%88%E5%BC%80%E5%8F%91/" style="font-size: 10px;">混合开发</a>
    </div>
  </div>

  
    
  <div class="widget-wrap">
    <h3 class="widget-title">Archives</h3>
    <div class="widget">
      <ul class="archive-list"><li class="archive-list-item"><a class="archive-list-link" href="/archives/2023/04/">April 2023</a></li><li class="archive-list-item"><a class="archive-list-link" href="/archives/2023/03/">March 2023</a></li></ul>
    </div>
  </div>


  
    
  <div class="widget-wrap">
    <h3 class="widget-title">Recent Posts</h3>
    <div class="widget">
      <ul>
        
          <li>
            <a href="/2023/04/02/%E5%B0%8F%E7%A8%8B%E5%BA%8F%E7%99%BB%E5%BD%95%E8%AE%BE%E8%AE%A1/">小程序登录设计</a>
          </li>
        
          <li>
            <a href="/2023/03/30/%E8%A7%82%E5%AF%9F%E8%80%85%E6%A8%A1%E5%BC%8F/">vue中的观察者模式</a>
          </li>
        
          <li>
            <a href="/2023/03/29/%E6%95%B0%E6%8D%AE%E5%8F%98%E6%9B%B4%E7%9A%84%E7%9B%91%E6%B5%8B/">数据变更的监测</a>
          </li>
        
          <li>
            <a href="/2023/03/26/%E9%97%AD%E5%8C%85/">闭包</a>
          </li>
        
          <li>
            <a href="/2023/03/21/instanceof%E5%8E%9F%E7%90%86/">instanceof原理</a>
          </li>
        
      </ul>
    </div>
  </div>

  
</aside>
        
      </div>
      <footer id="footer">
  
  <div class="outer">
    <div id="footer-info" class="inner">
      
      &copy; 2023 mobeiyanyun<br>
      Powered by <a href="https://hexo.io/" target="_blank">Hexo</a>
    </div>
  </div>
</footer>

    </div>
    <nav id="mobile-nav">
  
    <a href="/" class="mobile-nav-link">Home</a>
  
    <a href="/archives" class="mobile-nav-link">Archives</a>
  
</nav>
    


<script src="/js/jquery-3.4.1.min.js"></script>



  
<script src="/fancybox/jquery.fancybox.min.js"></script>




<script src="/js/script.js"></script>





  </div>
</body>
</html>